// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


/**
 * @fileoverview Defines constants and helper functions for parsing data from
 * the layer's manifest.  The property enumerations are broken into two types:
 * those that represent keys (Property) within the manifest and those that
 * represent valid values within the manifest.  The valid value properties are
 * denoted with a specific name under their owning Property.
 *
 * Validation functions exist to check for valid properties (keys) within the
 * manifest and valid values.  The validation functions ensure that the data
 * is the correct type and range of values.  They all take a single input
 * called data and return a boolean true if data is valid and false otherwise.
 * Note that the data parameter type for all validation functions are defined
 * as they are supposed to be.  The purpose of the functions are to check
 * external data, but internal usage should have the types checked at compile
 * time.
 *
 * Public properties:
 *   shellExtension.manifest.layer.Property - Valid keys in the Layer object.
 *   shellExtension.manifest.layer.State - Valid state values for the Layer's
 *       state and ondemand state.
 *   shellExtension.manifest.script.Property - Valid keys for a Script object.
 *   shellExtension.manifest.script.background.Property - Valid keys for a
 *       background script.
 *   shellExtension.manifest.script.content.Property - Valid keys for a
 *      content script.
 *   shellExtension.manifest.script.content.RunAt - Valid values for the
 *       run_at property.
 *
 * Validation functions:
 *   shellExtension.manifest.layer.validateId(data) - Validates a Layer's id.
 *   shellExtension.manifest.layer.validateState(data) - Validates the value of
 *       Layer properties that use state values.
 *   shellExtension.manifest.script.background.validate(data) - Validate the
 *       background script object.
 *   shellExtension.manifest.script.content.validate(data) - Validate the
 *       content script object.
 *   shellExtension.manifest.script.content.validateAllFrames(data) - Validate
 *       the value of the all_frames property in a content script.
 *   shellExtension.manifest.script.content.validateMatches(data) - Validate
 *       the value of the matches property in a content script.
 *   shellExtension.manifest.script.content.validateRunAt(data) - Validate the
 *       value of the run_at property in a content script.
 *   shellExtension.manifest.script.validate(data) - Validate a Script object.
 *   shellExtension.manifest.script.validateId(data) - Validate a Script's id.
 *   shellExtension.manifest.script.validateList(data) - Validate a list of
 *       Scripts.
 *   shellExtension.manifest.script.validateType(data) - Validate Script's
 *       type.
 *
 * @author jasonstredwick@google.com (Jason Stredwick)
 */


goog.provide('shellExtension.manifest');
goog.provide('shellExtension.manifest.layer');
goog.provide('shellExtension.manifest.script');
goog.provide('shellExtension.manifest.script.background');
goog.provide('shellExtension.manifest.script.content');

goog.require('shellExtension.utils');


/**
 * Valid layer properties.
 * @enum {string}
 */
shellExtension.manifest.layer.Property = {
  BACKGROUND_SCRIPTS: 'background_scripts',
  CONTENT_SCRIPTS: 'content_scripts',
  ID: 'id',
  ONDEMAND: 'ondemand',
  STATE: 'state'
};


/**
 * Valid values for the layer state property.
 * @enum {string}
 */
shellExtension.manifest.layer.State = {
  FIXED: 'fixed',
  OFF: 'off',
  ON: 'on'
};


/**
 * Validates the layer entry.  Should be an object.
 * @param {Object} data The data to validate.
 * @return {boolean} Whether the data is valid.
 */
shellExtension.manifest.layer.validate = function(data) {
  return shellExtension.utils.isType(data, 'object');
};


/**
 * Validate a layer id.
 * @param {string} data The data to check.
 * @return {boolean} Whether it is valid.
 */
shellExtension.manifest.layer.validateId = function(data) {
  return shellExtension.utils.isType(data, 'string');
};


/**
 * Validates the script list of a layer.  Should be an array-like object.
 * @param {!Array.<!Object>} data The data to validate.
 * @return {boolean} Whether the data is valid.
 */
shellExtension.manifest.layer.validateScriptList = function(data) {
  return shellExtension.utils.isType(data, 'object') && 'length' in data;
};


/**
 * Validate a layer's state.
 * @param {shellExtension.manifest.layer.State} data The data to check.
 * @return {boolean} Whether it is valid.
 */
shellExtension.manifest.layer.validateState = function(data) {
  var state = shellExtension.manifest.layer.State;
  return shellExtension.utils.inEnum(data, state);
};


/**
 * Valid types for layer scripts; includes JavaScript and CSS.
 * @enum {string}
 */
shellExtension.manifest.script.Property = {
  CSS_CODE: 'css_code',
  CSS_URL: 'css',
  JS_CODE: 'js_code',
  JS_URL: 'js'
};


/**
 * Background script properties found when loading data from a source.
 * @enum {string}
 */
shellExtension.manifest.script.background.Property = {
  JS_CODE: 'js_code',
  JS_URL: 'js'
  /**
   * TODO (jasonstredwick): Add in the ability to register these callbacks.
   * ON_DISABLE: 'onDisable',
   * ON_ENABLE: 'onEnable',
   * ON_INSTALL: 'onInstall',
   * ON_UNINSTALL: 'onUninstall'
   */
};


/**
 * Validates the background script entry.  Should be an object.
 * @param {!Object} data The data to validate.
 * @return {boolean} Whether the data is valid.
 */
shellExtension.manifest.script.background.validate = function(data) {
  return shellExtension.utils.isType(data, 'object');
};


/**
 * Content script properties found when loading data from a source.
 * @enum {string}
 */
shellExtension.manifest.script.content.Property = {
  ALL_FRAMES: 'all_frames',
  CSS_CODE: 'css_code',
  CSS_URL: 'css',
  MATCHES: 'matches',
  JS_CODE: 'js_code',
  JS_URL: 'js',
  RUN_AT: 'run_at'
};


/**
 * Content script values for when a content script should be injected. See
 * http://code.google.com/chrome/extensions/content_scripts.html.
 *     document_end injects after the dom body has been created but before
 *         imgs and frames have been added.
 *     document_idle injects when the page has time, and is guaranteed to
 *         be after the body has been created and just after body.onload.
 *     document_start injects before the dom body has been created.
 * @enum {string}
 */
shellExtension.manifest.script.content.RunAt = {
  DOCUMENT_END: 'document_end',
  DOCUMENT_IDLE: 'document_idle',
  DOCUMENT_START: 'document_start'
};


/**
 * Validates the content script entry.  Should be an array-like object.
 * @param {!Object} data The data to validate.
 * @return {boolean} Whether the data is valid.
 */
shellExtension.manifest.script.content.validate = function(data) {
  return shellExtension.utils.isType(data, 'object');
};


/**
 * Validates the content script entry for all_frames.  Should be a boolean-like
 * value; false, true, 'false', 'true'.
 * @param {string|boolean} data The data to validate.
 * @return {boolean} Whether the data is valid.
 */
shellExtension.manifest.script.content.validateAllFrames = function(data) {
  if (shellExtension.utils.isType(data, 'string') &&
      (data == 'true' || data == 'false')) {
    return true;
  } else if (shellExtension.utils.isType(data, 'boolean')) {
    return true;
  }
  return false;
};


/**
 * Validates the content script entry for matches.  Should be an array-like
 * object of strings.
 * @param {!Array.<string>} data The data to validate.
 * @return {boolean} Whether the data is valid.
 */
shellExtension.manifest.script.content.validateMatches = function(data) {
  return shellExtension.utils.isTypeArray(data, 'string');
};


/**
 * Validates the content script entry for run_at.  Should be a string from
 * shellExtension.manifest.script.content.RunAt.
 * @param {shellExtension.manifest.script.content.RunAt} data The data to
 *     validate.
 * @return {boolean} Whether the data is valid.
 */
shellExtension.manifest.script.content.validateRunAt = function(data) {
  var runAt = shellExtension.manifest.script.content.RunAt;
  return shellExtension.utils.inEnum(data, runAt);
};


/**
 * Validates a script.  Expected to be a string.
 * @param {string} data The data to validate.
 * @return {boolean} Whether the data is valid.
 */
shellExtension.manifest.script.validate = function(data) {
  return shellExtension.utils.isType(data, 'string');
};


/**
 * Validates a script's id.  Expected to be a string.
 * @param {string} data The data to validate.
 * @return {boolean} Whether the data is valid.
 */
shellExtension.manifest.script.validateId = function(data) {
  return shellExtension.utils.isType(data, 'string');
};


/**
 * Validates the script list.  Should be an array-like object of strings.
 * @param {!Array.<string>} data The data to validate.
 * @return {boolean} Whether the data is valid.
 */
shellExtension.manifest.script.validateList = function(data) {
  return shellExtension.utils.isTypeArray(data, 'string');
};


/**
 * Validates the scripts type.  Should be a string from
 * shellExtension.manifest.script.Property.
 * @param {shellExtension.manifest.script.Property} data The data to
 *     validate.
 * @return {boolean} Whether the data is valid.
 */
shellExtension.manifest.script.validateType = function(data) {
  var property = shellExtension.manifest.script.Property;
  return shellExtension.utils.inEnum(data, property);
};

